package com.siki.provider.service.Impl;

import cn.hutool.core.lang.Assert;
import com.siki.provider.dto.logistics.SaveLogisticsDTO;
import com.siki.provider.dto.logistics.UpdateLogisticsStatusDTO;
import com.siki.provider.service.LogisticsService;
import com.siki.salessystemcommon.entity.Commodity;
import com.siki.salessystemcommon.entity.Invoice;
import com.siki.salessystemcommon.entity.Logistics;
import com.siki.salessystemcommon.entity.Purchase;
import com.siki.salessystemcommon.entity.enumeration.InvoiceStatusEnum;
import com.siki.salessystemcommon.entity.enumeration.LogisticsStatusEnum;
import com.siki.salessystemcommon.mapper.InvoiceMapper;
import com.siki.salessystemcommon.mapper.LogisticsMapper;
import com.siki.salessystemcommon.mapper.PurchaseMapper;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.Optional;
import java.util.Random;

/**
 * @Author Siki
 * @Date 2020/12/17
 */

@Service
public class LogisticsServiceImpl implements LogisticsService {
    private final InvoiceMapper invoiceMapper;
    private final LogisticsMapper logisticsMapper;
    private final PurchaseMapper purchaseMapper;

    public LogisticsServiceImpl(InvoiceMapper invoiceMapper, LogisticsMapper logisticsMapper, PurchaseMapper purchaseMapper) {
        this.invoiceMapper = invoiceMapper;
        this.logisticsMapper = logisticsMapper;
        this.purchaseMapper = purchaseMapper;
    }

    @Override
    public void saveLogisticsInfo(SaveLogisticsDTO dto) {
        Logistics logistics = new Logistics();
        Invoice invoice = getInvoiceById(dto.getInvoiceId());
        Assert.isTrue(invoice.getInvoiceStatus().equals(InvoiceStatusEnum.NOT_SHIPPED),
                "未付款的出货单不能发物流");
        logistics.setLogisticsName(getLogisticsName())
                .setInvoiceId(dto.getInvoiceId())
                .setStartingPoint(getPurchaseByInvoiceId(dto.getInvoiceId())
                        .getStartingPoint())
                .setEndingPoint(getPurchaseByInvoiceId(dto.getInvoiceId())
                        .getEndingPoint())
                .setLogisticsStatus(LogisticsStatusEnum.NOT_RECEIVED);
        invoice.setInvoiceStatus(InvoiceStatusEnum.SHIPPED);
        invoiceMapper.updateById(invoice);
        logisticsMapper.insert(logistics);
    }

    @Override
    public void updateLogisticsStatus(UpdateLogisticsStatusDTO dto) {
        Logistics logistics = getLogisticsById(dto.getLogisticsId());
        Assert.isTrue(logistics.getLogisticsStatus().equals(LogisticsStatusEnum.NOT_RECEIVED),
                "已签收的物流无法修改");
        logistics.setLogisticsStatus(LogisticsStatusEnum.valueOf(dto.getStatus()))
                .setEndingPoint(dto.getEndingPoint());
        if (dto.getStatus().equals(LogisticsStatusEnum.RECEIVER.toString())) {
            Invoice invoice = getInvoiceById(logistics.getInvoiceId());
            invoice.setInvoiceStatus(InvoiceStatusEnum.END);
            invoiceMapper.updateById(invoice);
        }
        logisticsMapper.updateById(logistics);
    }

    @Override
    public void reLogistics(Long id) {
        Logistics logistics = getLogisticsById(id);
        logisticsMapper.updateById(logistics
                .setLogisticsStatus(LogisticsStatusEnum.RECEIVER));
    }


    /**
     * [私有方法] - 根据id查询物流
     *
     * @param id 采购清单id
     * @return Logistics 物流
     */
    private Logistics getLogisticsById(Long id) {
        return Optional.ofNullable(logisticsMapper.selectById(id))
                .orElseThrow(() -> new RuntimeException("该id:" + id + "有误"));
    }

    /**
     * [私有方法] - 根据id查询采购清单
     *
     * @param id 采购清单id
     * @return Purchase 采购清单
     */
    private Purchase getPurchaseById(Long id) {
        return Optional.ofNullable(purchaseMapper.selectById(id))
                .orElseThrow(() -> new RuntimeException("该id:" + id + "有误"));
    }

    /**
     * [私有方法] - 根据id获取出货单
     *
     * @param id 商品id
     * @return invoice 出货单
     */
    private Invoice getInvoiceById(Long id) {
        return Optional.ofNullable(invoiceMapper.selectById(id))
                .orElseThrow(() -> new RuntimeException("该id:" + id + "有误"));
    }

    /**
     * 根据出货单id查询对应的清单
     *
     * @param id 出货单id
     * @return Purchase 清单
     */
    private Purchase getPurchaseByInvoiceId(Long id) {
        return getPurchaseById(getInvoiceById(id).getPurchaseId());
    }

    /**
     * 生成物流编号
     *
     * @return 物流编号
     */
    private String getLogisticsName() {
        LocalDate year = LocalDate.now();
        return year + "-" + (new Random().nextInt(899) + 100);
    }
}
